package p.ithorns.example.statemachine.trans;

import com.alibaba.cola.statemachine.Action;
import com.alibaba.cola.statemachine.Condition;
import com.alibaba.cola.statemachine.StateMachine;
import com.alibaba.cola.statemachine.builder.NumbFailCallback;
import com.alibaba.cola.statemachine.builder.StateMachineBuilder;
import com.alibaba.cola.statemachine.builder.StateMachineBuilderFactory;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.List;

/**
 * StateManager
 *
 * @author Ht.L
 * @date 2023-09-09 20:22
 * @since 1.0.0
 */
@Slf4j
public class TransStateManager {

    public static void main(String[] args) {
        TransStateManager manager = new TransStateManager();
        Approval ctx = new Approval("approval");

        // StateMachine<FlowState, FlowEvent, String> machine = manager.build();
        List<Transition<Approval>> transitions = manager.buildTransitions(context -> "ACCEPT".equals(context.getResult()));


        StateMachine<FlowState, FlowEvent, Approval> machine = manager.build(ctx, transitions);
        System.out.println(machine.generatePlantUML());

        FlowState initState = FlowState.CREATED;
        FlowState nextState = machine.fireEvent(initState, FlowEvent.CREATE, ctx);
        System.out.println("执行 CREATE：" + nextState);

        ctx.setResult("ACCEPT");
        nextState = machine.fireEvent(nextState, FlowEvent.APPROVE, ctx);
        System.out.println("执行 APPROVE：" + nextState);

        nextState = machine.fireEvent(nextState, FlowEvent.RECEIVE, ctx);
        System.out.println("执行 RECEIVE：" + nextState);

        nextState = machine.fireEvent(nextState, FlowEvent.ASSIGN, ctx);
        System.out.println("执行 ASSIGN：" + nextState);

        nextState = machine.fireEvent(nextState, FlowEvent.COMPLETE, ctx);
        System.out.println("执行 COMPLETE：" + nextState);

        nextState = machine.fireEvent(nextState, FlowEvent.EVALUATE, ctx);
        System.out.println("执行 EVALUATE：" + nextState);
    }

    private Action<FlowState, FlowEvent, Approval> doAction() {
        return (from, to, on, ctx) -> {
            ctx.setState(to);
            log.info("[{}] ==> 执行{}: {} -> {}", ctx.getId(), on, from, to);
        };
    }

    public List<Transition<Approval>> buildTransitions(Condition<Approval> agree) {
        // 创建 -> 审批
        Transition<Approval> create = Transition.<Approval>builder()
                .from(FlowState.CREATED).to(FlowState.APPROVING).on(FlowEvent.CREATE)
                .build();

        // 审批(通过)  -> 待接收
        Transition<Approval> approve1 = Transition.<Approval>builder()
                .from(FlowState.APPROVING).to(FlowState.RECEIVING).on(FlowEvent.APPROVE)
                .when(agree)// "AGREE".equals(ctx.getResult())
                .build();

        // 审批(不通过) -> 完结
        Transition<Approval> approve2 = Transition.<Approval>builder()
                .from(FlowState.APPROVING).to(FlowState.COMPLETED).on(FlowEvent.APPROVE)
                .when(ctx -> !agree.isSatisfied(ctx)) // "REFUSE".equals(ctx.getResult())
                .build();

        // 待接收 -> 已接收
        Transition<Approval> receive = Transition.<Approval>builder()
                .from(FlowState.RECEIVING).to(FlowState.RECEIVED).on(FlowEvent.RECEIVE)
                .build();

        // 已接收 -> 指派
        Transition<Approval> assign = Transition.<Approval>builder()
                .from(FlowState.RECEIVED).to(FlowState.ASSIGNED).on(FlowEvent.ASSIGN)
                .build();

        // 指派 -> 评价
        Transition<Approval> complete = Transition.<Approval>builder()
                .from(FlowState.ASSIGNED).to(FlowState.COMPLETED).on(FlowEvent.COMPLETE)
                .build();

        // 评价 -> 完结
        Transition<Approval> evaluate = Transition.<Approval>builder()
                .from(FlowState.COMPLETED).to(FlowState.EVALUATED).on(FlowEvent.EVALUATE)
                .build();


        List<Transition<Approval>> bundles = new ArrayList<>();
        bundles.add(create);
        bundles.add(approve1);
        bundles.add(approve2);
        bundles.add(receive);
        bundles.add(assign);
        bundles.add(complete);
        bundles.add(evaluate);
        return bundles;
    }

    private boolean condition(String approvalResult) {
        return true; // "ACCEPT".equals(approvalResult);
    }

    private StateMachine<FlowState, FlowEvent, Approval> build(Approval approval, List<Transition<Approval>> transitions) {
        StateMachineBuilder<FlowState, FlowEvent, Approval> builder = StateMachineBuilderFactory.create();
        builder.setFailCallback(new TransFailCallback<>());

        for (Transition<Approval> state : transitions) {
            if (state.isExternal()) {
                builder.externalTransition()
                        .from(state.getFrom())
                        .to(state.getTo())
                        .on(state.getOn())
                        .when(state.getWhen())
                        .perform(doAction());
            }
        }
        return builder.build(approval.getId());

    }

    public StateMachine<FlowState, FlowEvent, Approval> build() {
        StateMachineBuilder<FlowState, FlowEvent, Approval> builder = StateMachineBuilderFactory.create();
        builder.setFailCallback(new NumbFailCallback<>());

        // 创建 -> 审批
        builder.externalTransition()
                .from(FlowState.CREATED).to(FlowState.APPROVING).on(FlowEvent.CREATE);

        // 审批 -> 待接收
        builder.externalTransition()
                .from(FlowState.APPROVING).to(FlowState.RECEIVING).on(FlowEvent.APPROVE)
                .when(context -> true);

        // 审批 -> 完成
        builder.externalTransition()
                .from(FlowState.APPROVING).to(FlowState.COMPLETED).on(FlowEvent.APPROVE)
                .when(context -> false);

        // 待接收 -> 已接收
        builder.externalTransition()
                .from(FlowState.RECEIVING).to(FlowState.RECEIVED).on(FlowEvent.RECEIVE);

        // 已接收 -> 指派
        builder.externalTransition()
                .from(FlowState.RECEIVED).to(FlowState.ASSIGNED).on(FlowEvent.ASSIGN);

        // 指派 -> 评价
        builder.externalTransition()
                .from(FlowState.ASSIGNED).to(FlowState.COMPLETED).on(FlowEvent.COMPLETE);

        // 评价 -> 完结
        builder.externalTransition()
                .from(FlowState.COMPLETED).to(FlowState.EVALUATED).on(FlowEvent.EVALUATE);

        return builder.build("trans");
    }


}